home *** CD-ROM | disk | FTP | other *** search
- Path: chronicle.mti.sgi.com!austern
- From: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
- Newsgroups: comp.std.c++
- Subject: Re: Portability. Modules. WAS: RE: Are all Windows programs ill-formed?
- Date: 20 Feb 1996 10:56:30 PST
- Organization: GABI Software, Sarl.
- Approved: austern@isolde.mti.sgi.com
- Message-ID: <KANZE.96Feb20112203@slsvewt.lts.sel.alcatel.de>
- References: <UPMAIL04.199602192354280583@msn.com>
- NNTP-Posting-Host: isolde.mti.sgi.com
- X-Original-Date: 20 Feb 1996 10:22:03 GMT
- In-Reply-To: "Eugene Lazutkin"'s message of 20 Feb 96 07:15:52 GMT
- Apparently-To: std-c++@ncar.ucar.edu
- X-Auth: PGPMoose V1.1 PGP comp.std.c++
- iQBVAwUBMSoZaEy4NqrwXLNJAQHwXQH8D3tdSLEn2dG6HcMayOcHKlXcBVR0+Xzm
- 0yqKrmHA6OQwSFuMK7vk/PNu4DpWVsaCoROz4gAuCH9pX/j53xCagg==
- =+v5v
- Originator: austern@isolde.mti.sgi.com
-
- In article <UPMAIL04.199602192354280583@msn.com> "Eugene Lazutkin"
- <INT@msn.com> writes:
-
- |> On Tuesday, February 13, 1996 7:48 AM,
- |> James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de> wrote:
- |> > In article <01BAF61B.3131B100@dino.int.com> Eugene Lazutkin
- |> > <eugene@int.com> writes:
-
- |> > The oldest one, rarely used except for the simplest cases today, is to
- |> > design the list such that the initial initialization to 0 is adequate,
- |> > and give it a special no-op constructor. Thus, for example, my
- |> > command line parser class maintains a list of options (staticly
- |> > declared objects); a NULL pointer signifies an empty list, and the
- |> > constructor does nothing. Thus, it doesn't matter if the options are
- |> > constructed (and register themselves) before the list.
-
- |> It doesn't help to create a simple double-linked ring. Not all
- |> containers can be built on a single-linked list or a tree structure.
- |> E.g., any member of a double linked ring can exclude itself from the
- |> list automatically by its destructor at any time. You can't do it
- |> with single-linked list or with double-linked list (not ring).
-
- I've used it for double-linked lists:-). It does mean 1) that the
- list itself is special, and 2) a little bit more code to check the
- special case (linked to head/tail). In the case of 1, this is
- generally the case anyway. For 2, in the cases I've used it,
- performance hasn't been a problem.
-
- More generally, most of the classes I have that use this are
- associative arrays. The actual array is dynamically allocated (on the
- heap), and the only static data is a pointer. The access routines
- check for NULL, and create the array as needed.
-
- |> BTW, who frees the allocated memory? When? How can I specify the
- |> order of destruction? ObjectSpace's STL has problems with that.
- |> The program using this STL will leak. They can't eleminate this
- |> problem. OK, they have a work around. But it is very inefficient:
- |> they use per-object allocators instead of per-class.
-
- Order of destruction is undefined. In general, IMHO, destructors
- shouldn't be doing much, so that order of destruction is not a
- significant problem.
-
- In most cases of static maps, I simply let the memory leak. Since I
- couldn't free it before the static destructors run anyway, there's
- really no point; once the process finishes, the OS recovers it anyway.
- (I know that this isn't particularly elegant, but solving real
- problems has had priority until now.)
-
- A potential solution would have the users of the class enrol/deenrol.
- When the last user deenrols, clean up.
-
- |> > The more frequent solution today is to have a function returning a
- |> > reference to a local static object. The object will be constructed
- |> > the first time the function is called. The enrolment functions in the
- |> > Item's call the function to get the actual list object.
-
- |> Does this static object have any constructors? Or its components?
- |> Is it based on some class without constructors? If not, who will
- |> be initialize it? And how? Who will deinitialize it? A lot of
- |> problems.
-
- Of course, it has constructors. And destructors. The constructors
- are called the first time the function is called. Note that this is
- the only solution (that I know of, at least) that is fully conforming,
- and works even if the implementation does not initialize everything
- before main.
-
- There may still be problems with order of destruction. According to
- the current draft (Jan. 96), all static objects (including those with
- block scope) must be destructed in the reverse order of their
- construction, so there is at least one guarantee, although probably
- not the one you need, at least presuming that order of construction
- refers to the order the constructors were entered, and not the order
- they were left.
-
- Note that most compilers do not yet implement this order of
- destruction. If I remember right, for example, the Sun compiler
- (4.0.1) will destruct all file (namespace) scope static objects first,
- and then block scope statics.
-
- |> Of course, both these solutions work just fine in certain specific
- |> cases. But it is not a generic answer. It is a trick.
-
- I'll accept this for the first solution. I only use it in special
- cases, and in modern code, practically not at all. The second
- solution is not a trick, however; it is the standard generic answer,
- which works in all cases, and ensures destruction. It may lead to
- problems in the order of destruction, but no more than any other
- solution. The best solution here is to not allow destructors to
- access *other* static objects.
-
- |> > I often encapsulate the above solution in a SharedList interface
- |> > class. All instances of the SharedList actually refer to the same
- |> > list object. The SharedList only contains a pointer to the actual
- |> > list object, and forwards all requests to it. The pointer is
- |> > initialized by calling the function above in the constructor.
- |> >
- |> > |> Alternative way: include all items into the container manually and
- |> > |> don't forget to do this initialization every time when you use this
- |> > |> container in your program.
- |> >
- |> > This is extremely error prone (as you also point out). If you are
- |> > willing to accept that all of the objects are known in the same
- |> > compilation unit, you might as well define them there, and let the
- |> > guaranteed order of construction within the compilation unit do the
- |> > trick.
-
- |> This is C++, not Pascal. We have separate units. I think it is too
- |> strong requirement to put some logically different items together.
- |> I think it is too error-prone.
-
- I basically agree, although if the objects aren't related in any way,
- then the order of construction between them shouldn't matter:-). In
- fact, of course, I use the registry idiom in almost all cases where I
- have something to parse, including the command line options. I find
- it nice that the option is declared near its point of use, and that no
- other code (including main) knows about it. I also find it nice that
- I can add a command to a parser without changing a single line of
- existing code.
- --
- James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
- GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
- Conseils, itudes et rialisations en logiciel orienti objet --
- -- A la recherche d'une activiti dans une region francophone
- ---
- [ To submit articles: Try just posting with your newsreader. If that fails,
- use mailto:std-c++@ncar.ucar.edu
- FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
- Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
- Comments? mailto:std.c++-request@ncar.ucar.edu
- ]
-